/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * NewJFrame.java
 *
 * Created on 01-Apr-2009, 17:18:48
 */

package edu.napier.soc.xfdm.uci;

import edu.napier.soc.xfdm.model.EntityType;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ContainerEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import edu.napier.soc.xfdm.uci.EntityTypeView.RelationshipModel.Cardinality;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import edu.napier.soc.xfdm.uci.EntityTypeView.RelationshipModel;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerListener;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.JToolBar.Separator;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 *
 * @author Thomas
 */
public class DatabaseView extends javax.swing.JFrame {

	private List<EntityTypeView> panels = new LinkedList<EntityTypeView>();
	private boolean relationships = true;
	private boolean supertypes = true;
	
    /** Creates new form NewJFrame */
    public DatabaseView() {
        initComponents();
    }

	private final Random r = new Random();

	public DatabaseView(List<EntityType> entityTypes, JFrame owner) {
		super(owner.getTitle() + " - Visual Viewer" );
		setIconImage(owner.getIconImage());
		contentPane.setLayout(null);
		contentPane.setPreferredSize(new Dimension(800, 550));
		add(contentPane, BorderLayout.CENTER);
		initComponents();

		for (EntityType e : entityTypes) {
			EntityTypeView view = new EntityTypeView(e);
			addEntityTypeView(view);
		}
		setLocationRelativeTo(owner);
		contentPane.addComponentListener(new ComponentAdapter() {

			@Override
			public void componentResized(ComponentEvent e) {
				for (Component c : contentPane.getComponents()) {
					c.setLocation(checkInBounds(c, c.getLocation()));
				}
				repaint();
			}
		});
	}

	public void addEntityTypeView(EntityTypeView view) {
		panels.add(view);
		Dimension viewSize = view.getPreferredSize();
		Dimension paneSize = contentPane.getPreferredSize();
		view.addMouseListener(ml);
		view.addMouseMotionListener(ml);
		view.setSize(view.getPreferredSize());
		view.setLocation(r.nextInt((int)(paneSize.getWidth() - viewSize.getWidth())),
				r.nextInt((int)(paneSize.getHeight() - viewSize.getHeight())));
		contentPane.add(view);
	}

	private void drawRelationship(Graphics2D g2, RelationshipModel rel,
			EntityTypeView from, EntityTypeView to) {
			int pX = from.getX() + (from.getWidth() / 2);
			int pY = from.getY() + (from.getHeight() / 2);
			int p1X = to.getX() + (to.getWidth() / 2);
			int p1Y = to.getY() + (to.getHeight() / 2);
			Line2D line = new Line2D.Float(pX, pY, p1X, p1Y);
			g2.setStroke(new BasicStroke(2));
			Color old = g2.getColor();
			if (rel.getCardinality() == Cardinality.SUPERTYPE) {
				if (!supertypes) {
					return;
				}
				g2.setColor(Color.RED);
				//g2.drawLine(pX, pY, p1X, p1Y);
				g2.draw(line);
				g2.setColor(old);
				return;
			}
			if (!relationships) {
				return;
			}
//			g2.drawLine(pX, pY, p1X, p1Y);
			g2.draw(line);
			String label = rel.getFunction().getName() + " "
					+ rel.getCardinality().getName();

			int difX = Math.abs(pX - p1X) / 2;
			int difY = Math.abs(pY - p1Y) / 2;
			int startX = Math.min(pX, p1X);
			int startY = Math.min(pY, p1Y);
			int labelW = g2.getFontMetrics().stringWidth(label);
			int labelH = g2.getFontMetrics().getHeight();
			int offsetX = startX + difX - (labelW / 2);
			int offsetY = startY + difY - (labelH / 2);
			g2.setColor(this.getBackground());
			g2.fillRect(offsetX - 2, offsetY, labelW + 4, labelH + 2);
			g2.setColor(old);
			g2.drawString(label, offsetX, offsetY + labelH);
	}

	private void drawEntityTypeView(Graphics2D g2, EntityTypeView e) {
		for (RelationshipModel rel : e.getRelationships()) {
			EntityTypeView to = null;

			for (EntityTypeView current : panels) {
				if (current.getEntityType() == rel.getRelationshipTo()) {
					to = current;
					break;
				}
			}

			if (to != null) {
				drawRelationship(g2, rel, e, to);
			}
		}
	}

	private void drawDatabaseView(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
				RenderingHints.VALUE_STROKE_NORMALIZE);

		for (EntityTypeView view : panels) {
			drawEntityTypeView(g2, view);
		}
	}

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        toolBar = new JToolBar();
        inheritanceButton = new JToggleButton();
        relationshipsButton = new JToggleButton();
        seperator = new Separator();
        imageButton = new JButton();

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        toolBar.setRollover(true);

        inheritanceButton.setIcon(new ImageIcon(getClass().getResource("/edu/napier/soc/xfdm/resources/inher.png"))); // NOI18N
        inheritanceButton.setToolTipText("Show Inheritance");
        inheritanceButton.setFocusable(false);
        inheritanceButton.setHorizontalTextPosition(SwingConstants.CENTER);
        inheritanceButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        inheritanceButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                inheritanceButtonActionPerformed(evt);
            }
        });
        toolBar.add(inheritanceButton);

        relationshipsButton.setIcon(new ImageIcon(getClass().getResource("/edu/napier/soc/xfdm/resources/rels.png"))); // NOI18N
        relationshipsButton.setToolTipText("Show Relationships");
        relationshipsButton.setFocusable(false);
        relationshipsButton.setHorizontalTextPosition(SwingConstants.CENTER);
        relationshipsButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        relationshipsButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                relationshipsButtonActionPerformed(evt);
            }
        });
        toolBar.add(relationshipsButton);
        toolBar.add(seperator);

        imageButton.setIcon(new ImageIcon(getClass().getResource("/edu/napier/soc/xfdm/resources/image.png"))); // NOI18N
        imageButton.setToolTipText("Save to Image");
        imageButton.setFocusable(false);
        imageButton.setHorizontalTextPosition(SwingConstants.CENTER);
        imageButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        imageButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                imageButtonActionPerformed(evt);
            }
        });
        toolBar.add(imageButton);

        getContentPane().add(toolBar, BorderLayout.PAGE_START);

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void inheritanceButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_inheritanceButtonActionPerformed
		supertypes = !supertypes;
		repaint();
}//GEN-LAST:event_inheritanceButtonActionPerformed

	private void relationshipsButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_relationshipsButtonActionPerformed
		relationships = !relationships;
		repaint();
}//GEN-LAST:event_relationshipsButtonActionPerformed

	private void imageButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_imageButtonActionPerformed
		File f = MainGUI.saveFile(this,
				new FileNameExtensionFilter("PNG File (*.png)", "png"));

		if (f == null) {
			return;
		}

		BufferedImage out = new BufferedImage(contentPane.getWidth(),
				contentPane.getHeight(), BufferedImage.TYPE_INT_RGB);
		contentPane.paintAll(out.getGraphics());
		try {
			if (!f.getName().toLowerCase().endsWith(".png")) {
				f = new File(f.getAbsolutePath() + ".png");
			}
			ImageIO.write(out, "png", f);
		} catch (IOException ex) {
			ex.printStackTrace();
		}
}//GEN-LAST:event_imageButtonActionPerformed

	public Point checkInBounds(Component c, Point p) {
		if (p.getX() < 0) {
			p.setLocation(0, p.getY());
		} else if (p.getX() + c.getWidth() > contentPane.getWidth()) {
			p.setLocation(contentPane.getWidth() - c.getWidth(), p.getY());
		}
		if (p.getY() < 0) {
			p.setLocation(p.getX(), 0);
		} else if (p.getY() + c.getHeight() > contentPane.getHeight()) {
			p.setLocation(p.getX(), contentPane.getHeight() - c.getHeight());
		}
		return p;
	}

	private JPanel contentPane = new JPanel() {

		@Override
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			drawDatabaseView(g);
		}
	};

	private MouseAdapter ml = new MouseAdapter() {
		private JComponent dragging;
		private int x;
		private int y;

		@Override
		public void mousePressed(MouseEvent e) {
			dragging = (JComponent)e.getSource();
			x = e.getX();
			y = e.getY();
		}

		@Override
		public void mouseDragged(MouseEvent e) {
			Point p = SwingUtilities.convertPoint(dragging, e.getX() - x,
					e.getY() - y, contentPane);

			dragging.setLocation(checkInBounds(dragging, p));
			repaint();
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			dragging = null;
		}
	};

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private JButton imageButton;
    private JToggleButton inheritanceButton;
    private JToggleButton relationshipsButton;
    private Separator seperator;
    private JToolBar toolBar;
    // End of variables declaration//GEN-END:variables

}
